﻿using LLMEvaluation.Framework;
using StableDiffusionTools.Oobabooga;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace LLMEvaluation.Utils
{
    public static class ImportExportUtil
    {
        private static readonly JsonSerializerOptions options = new JsonSerializerOptions { WriteIndented = true, Converters = { new JsonStringEnumConverter(new JsonNamingPolicyLowercase()) } };

        public static List<RunEntry> Import(string[] fileNames)
        {
            List< RunEntry> result = new List<RunEntry>();

            for (int i = 0; i < fileNames.Length; i++)
            {
                try
                {
                    using (var file = File.OpenText(fileNames[i]))
                    {
                        string json = file.ReadToEnd();
                        var item = JsonSerializer.Deserialize<RunEntry>(json, options);
                        item.UpdateAll();
                        result.Add(item);
                    }
                }
                catch (JsonException jEx)
                {
                    if (jEx.HResult == -2146233088)
                    {
                        try
                        {
                            var items = Import(fileNames[i]);
                            if(items.Count > 0)
                            {
                                result.AddRange(items);
                            }
                        }
                        catch (Exception) { }
                    }
                }
                catch (Exception) { }
            }

            return result;
        }

        public static List<RunEntry> Import(string fileName)
        {
            List<RunEntry> result = new List<RunEntry>();

            try
            {
                using (var file = File.OpenText(fileName))
                {
                    var item = JsonSerializer.Deserialize<List<RunEntry>>(file.ReadToEnd(), options);
                    for (int i = 0; i < item.Count; i++)
                    {
                        item[i].UpdateAll();
                        result.Add(item[i]);
                    }
                }
            }
            catch (Exception) { }

            return result;
        }

        public static bool Export(string fileName, RunEntry entry)
        {
            bool result = false;

            try
            {
                string json = JsonSerializer.Serialize(entry, options);
                var exists = File.Exists(fileName);
                var fileMode = exists ? FileMode.Truncate : FileMode.CreateNew;
                using (var stream = File.Open(fileName, fileMode, FileAccess.Write, FileShare.None))
                using (var writer = new StreamWriter(stream))
                {
                    writer.Write(json);
                }
                result = true;
            }
            catch (Exception) { }

            return result;
        }

        public static bool Export(string fileName, List<RunEntry> entries)
        {
            bool result = false;

            try
            {
                string json = JsonSerializer.Serialize(entries, options);
                var exists = File.Exists(fileName);
                var fileMode = exists ? FileMode.Truncate : FileMode.CreateNew;
                using (var stream = File.Open(fileName, fileMode, FileAccess.Write, FileShare.None))
                using (var writer = new StreamWriter(stream))
                {
                    writer.Write(json);
                }
                result = true;
            }
            catch (Exception) { }

            return result;
        }

        public static bool TrySerialize<T>(T entries, out string outJSON)
        {
            string outT = null;
            try
            {
                outT = JsonSerializer.Serialize(entries, options);
            }
            catch (Exception) { }

            outJSON = outT;

            return outJSON != null;
        }

        public static bool TryDeserialize<T>(string json, out T outResult)
        {
            T outT = default(T);
            try
            {
                outT = JsonSerializer.Deserialize<T>(json, options);
            }
            catch (Exception) { }

            outResult = outT;

            return outResult != null;
        }
    }
}
